import * as d3 from 'd3'
export class BubbleChart {
  divId = ''
  data = []
  chart = {}
  category = []
  color = d3.scaleOrdinal()
  colorScale = {}
  constructor (divId) {
    this.divId = divId
  }

  draw () {
    this.initChart()
    this.initAxis()
    this.drawLabel()
    this.drawLegend()
    this.drawScatter()
  }

  update () {
    this.initAxis()
    this.drawLegend()
    this.drawScatter()
  }

  initChart () {
    this.chart.padding = {
      left: 20,
      right: 50,
      top: 20,
      bottom: 20
    }
    this.chart.divHeight = document.getElementById(this.divId).offsetHeight -
      this.chart.padding.top -
      this.chart.padding.bottom
    this.chart.divWidth = document.getElementById(this.divId).offsetWidth -
      this.chart.padding.left -
      this.chart.padding.right

    this.chart.svg = d3
      .select('#' + this.divId)
      .append('svg')
      .attr('width', this.chart.divWidth +
        this.chart.padding.left +
        this.chart.padding.right
      )
      .attr('height', this.chart.divHeight +
        this.chart.padding.top +
        this.chart.padding.bottom
      )
      .attr('class', 'svg_chart')
  }

  initAxis () {
    this.chart.xScale = d3.scaleLinear()
      .domain([0, d3.max(this.data, function (d) {
        return +d.x
      })])
      .range([this.chart.padding.left, this.chart.divWidth])

    this.chart.yScale = d3.scaleLinear()
      .domain([0, d3.max(this.data, function (d) {
        return +d.y
      })])
      .range([this.chart.divHeight, this.chart.padding.top])

    this.chart.rScale = d3.scaleLinear()
      .domain(d3.extent(this.data.map(d => +d.value)))
      .range([4, 10])

    this.color.domain(this.category).range(d3.schemeCategory10)

    this.chart.xAxis = d3
      .axisBottom()
      .scale(this.chart.xScale)
      .ticks(this.data.length)
    //   .tickFormat((d) => 2015 + parseInt(d))
    this.chart.yAxis = d3.axisLeft().scale(this.chart.yScale)

    if (this.chart.svg.select('.xAxis')._groups[0][0] !== undefined) {
      this.chart.svg.select('.xAxis').call(this.chart.xAxis)
    } else {
      this.chart.svg
        .append('g')
        .attr('class', 'xAxis')
        .attr('transform', 'translate(0,' + this.chart.divHeight + ')')
        .call(this.chart.xAxis)
    }

    if (this.chart.svg.select('.yAxis')._groups[0][0] !== undefined) {
      this.chart.svg.select('.yAxis').call(this.chart.yAxis)
    } else {
      this.chart.svg
        .append('g')
        .attr('class', 'yAxis')
        .attr('transform', 'translate(' + this.chart.padding.left + ')')
        .call(this.chart.yAxis)
    }
  }

  drawScatter () {
    let scatter = this.chart.svg.selectAll('.scatter')
      .data(this.data)

    scatter.select('circle')
      .transition()
      .duration(750)
      .attr('cx', d => this.chart.xScale(d.x))
      .attr('cy', d => this.chart.yScale(d.y))

    let scatterEnter = scatter.enter()
      .append('g')
      .attr('class', 'scatter')

    scatterEnter.append('circle')
      .attr('cx', d => this.chart.xScale(d.x))
      .attr('cy', d => this.chart.yScale(d.y))
      .attr('r', 0)
      .attr('class', d => d.category)
      .style('fill', d => this.color(d.category))
      .style('stroke', 'black')
      .transition()
      .duration(750)
      .attr('r', d => {
        return this.chart.rScale(d.value).toFixed(2)
      })

    let scatterExit = scatter.exit()
      .transition()
      .duration(750)
      .remove()

    scatterExit.select('circle')
      .attr('cr', 0)
  }
  drawLabel () {
    // 标题
    this.chart.svg
      .append('text')
      .attr('x', this.chart.divWidth / 2 - this.title.length)
      .attr('y', this.chart.divHeight + this.chart.padding.bottom * 1.7)
      .text(this.title)
    // y轴
    this.chart.svg
      .append('text')
      .attr('x', this.chart.padding.left)
      .attr('y', this.chart.padding.top - 5)
      .text(this.yLabel)
    // x轴
    this.chart.svg
      .append('text')
      .attr('x', this.chart.divWidth + 5)
      .attr('y', this.chart.divHeight)
      .text(this.xLabel)
  }

  drawLegend () {
    let legendWidth = 15
    let legendHeight = 15
    let legends = this.chart.svg
      .selectAll('.legend')
      .data(this.category)
    let legendEnter = legends.enter()
      .append('g')
      .attr('class', 'legend')

    legendEnter.append('rect')
      .attr('x', this.chart.divWidth + 5)
      .attr('y', (_, i) => this.chart.padding.top + legendHeight * i)
      .attr('width', 0)
      .attr('height', legendHeight - 5)
      .style('fill', d => this.color(d))

    legendEnter.append('text')
      .attr('x', this.chart.divWidth + legendWidth * 1.3 + 5)
      .attr('y', (d, i) => this.chart.padding.top + legendHeight * i + legendHeight / 2)
      .text(String)
      .style('font-size', 1e-6)

    let legendUpdate = legendEnter.merge(legends)

    legendUpdate.select('rect')
      .transition()
      .duration(750)
      .attr('width', legendWidth)

    legendUpdate.select('text')
      .transition()
      .duration(750)
      .style('font-size', 10)

    let legendExit = legends.exit()
      .transition()
      .duration(750)
      .remove()

    legendExit.select('rect')
      .attr('width', 0)

    legendExit.select('text')
      .style('stroke-opacity', 1e-6)
  }
}
